#include "comm_def.h"
#include "mz_zip_process.h"
#include "mz_file_info.h"
#include "mz_getopt.h"
#include "mz_debug.h"

#include <windows.h>
#include <stdio.h>
#define BUFSIZE 1024

static HANDLE hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup, hSaveStdout;

static int _error_exit (LPTSTR lpszMessage) {
	SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout);
	printf("%s\nanny key to exit.\n", lpszMessage);
	getchar();
	exit(-1);
	return -1;
}

static BOOL _create_child_process( LPTSTR lpProgram ) { 
	PROCESS_INFORMATION piProcInfo; 
	STARTUPINFO siStartInfo;
	BOOL bFuncRetn = FALSE; 

	ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
	ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
	siStartInfo.cb = sizeof(STARTUPINFO); 

	bFuncRetn = CreateProcess ( NULL, lpProgram, NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo);
	if (bFuncRetn == 0) {
		_error_exit("CreateProcess failed\n");
		return -1;
	} else {
		CloseHandle(piProcInfo.hProcess);
		CloseHandle(piProcInfo.hThread);
		return bFuncRetn;
	}
}

static int _open_sub_process(char* path) {
	SECURITY_ATTRIBUTES saAttr; 
	int fSuccess;

	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
	saAttr.bInheritHandle = TRUE; 
	saAttr.lpSecurityDescriptor = NULL; 


	//redirecting child process's STDOUT
	hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); 

	if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) {
		_error_exit("Stdout pipe creation failed\n");
	}

	if (!SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr)) {
		_error_exit("Redirecting STDOUT failed");
	}

	fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup , 0, FALSE, DUPLICATE_SAME_ACCESS);
	if( !fSuccess ) {
		_error_exit("DuplicateHandle failed");
	}
	CloseHandle(hChildStdoutRd);

	
	fSuccess = _create_child_process(path);
	if (!fSuccess) {
		_error_exit("Create process failed"); 
	}

	// set parent process as origin setting
	if (!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout)) {
		_error_exit("Re-redirecting Stdout failed\n");
	}
	return 0;
}

static int _readFromPipe() { 
	int fSuccess;
	DWORD dwRead;
	CHAR chBuf[BUFSIZE] = {0}; 

	if (!CloseHandle(hChildStdoutWr)) {
		_error_exit("Closing handle failed");
	}

	for (;;) { 
		memset(chBuf, 0, sizeof(chBuf));
		fSuccess = ReadFile( hChildStdoutRdDup, chBuf, BUFSIZE - 1, &dwRead, NULL);
		if( !fSuccess || dwRead == 0) {
			break; 
		}
		printf("%s", chBuf);
	}
	return 0;
}

int mz_zip_process() {
	char buf[1024] = {0};
	char* pwd = 0;
	char* srcfile = 0;
	char* tagfile = 0;
	unsigned int i = 0;
	unsigned int len = 0;
	unsigned int pos = 0;

	MZ_ARG_INFO* parg = get_arg_result("add");
	MZ_ARG_INFO* poutput = get_arg_result("o");
	MZ_ARG_INFO* ppwd = get_arg_result("p");

	char** parr = (char**)parg->param_arr;

	if (poutput && 0 == poutput->param_arr) {
		tagfile = "_md5_default_output.";
	} else {
		tagfile = ((char**)poutput->param_arr)[0];
	}

	if (ppwd && 0 != ppwd->param_arr) {
		pwd = ((char**)ppwd->param_arr)[0];
	}

	for (; i < parg->param_cnt; ++i) {
		len += strlen(parr[i]);
		len += 1; //space
	}
	srcfile = (char*) malloc(len + 1);
	memset(srcfile, 0, len + 1);
	for (i = 0; i < parg->param_cnt; ++i) {
		int le = strlen(parr[i]);
		strncpy(srcfile + pos, parr[i], le + 1);
		pos += le;
		*(srcfile + pos) = ' ';
		pos += 1;
	}

	if (pwd) {
		sprintf(buf, "7z a -tzip -p%s %s _md5list.txt %s", pwd, srcfile, tagfile);
	} else {
		sprintf(buf, "7z a -tzip %s _md5list.txt %s", tagfile, srcfile);
	}	
	_open_sub_process(buf);
	_readFromPipe(); 
	return 0;
}